﻿using System;
using System.Collections.Generic;
using System.Text;

using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Security.Permissions;


namespace Tickz.Commonz
{
    [AspNetHostingPermission(SecurityAction.Demand, Level = AspNetHostingPermissionLevel.Minimal)]
    public class ValidatorContainer : IObserver
    {
        /// <summary>
        /// 是否开启验证
        /// </summary>
        private bool isStartCheck;

        /// <summary>
        /// 验证器所在页对象
        /// </summary>
        private Page cPage;

        /// <summary>
        /// 客户端验证器对象名
        /// </summary>
        private string clientValidatorName;

        /// <summary>
        /// 验证组名
        /// </summary>
        private string groupName;

        /// <summary>
        /// 错误数量
        /// </summary>
        //private int errorCount;

        /// <summary>
        /// 前台呈现脚本代码
        /// </summary>
        private StringBuilder renderString;

        /// <summary>
        /// 验证器列表
        /// </summary>
        private List<ISubject> validatorList;

        /// <summary>
        /// 是否开启验证
        /// </summary>
        public bool IsStartCheck
        {
            get { return isStartCheck; }
            set { isStartCheck = value; }
        }

        /// <summary>
        /// 客户端验证器对象名
        /// </summary>
        public string ClientValidatorName
        {
            get { return clientValidatorName; }
            set { clientValidatorName = value; }
        }

        /// <summary>
        /// 验证组名
        /// </summary>
        public string GroupName
        {
            get { return groupName; }
            set { groupName = value; }
        }

        #region 是否通过验证
        /// <summary>
        /// 是否通过验证
        /// </summary>
        public bool IsAllPass
        {
            get { return GetPassStat(); }
        }

        /// <summary>
        /// 获取验证状态
        /// </summary>
        /// <returns></returns>
        private bool GetPassStat()
        {
            foreach (ISubject o in validatorList)
            {
                if (!o.IsPass)
                    return false;
            }
            return true;
        }
        #endregion

        /// <summary>
        /// 是否开启验证
        /// </summary>
        /// <param name="_isStartCheck"></param>
        public ValidatorContainer(bool _isStartCheck)
        {
            validatorList = new List<ISubject>();
            clientValidatorName = "Validator";
            this.isStartCheck = _isStartCheck;
        }

        /// <summary>
        /// 验证器列表
        /// </summary>
        public List<ISubject> ValidatorList
        {
            get { return validatorList; }
            set { validatorList = value; }
        }

        /// <summary>
        /// 添加字符串验证器
        /// </summary>
        /// <param name="_validator">字符串验证器对象</param>
        public Validator<string> Add(Validator<string> _validator)
        {
            if (this.groupName != "_All")
                if (this.groupName != _validator.GroupName)
                    _validator.Ignore = true;
            validatorList.Add(_validator);
            return _validator;
        }

        /// <summary>
        /// 添加整数验证器
        /// </summary>
        /// <param name="_validator">整数验证器对象</param>
        public Validator<int> Add(Validator<int> _validator)
        {
            if (this.groupName != "_All")
                if (this.groupName != _validator.GroupName)
                    _validator.Ignore = true;
            validatorList.Add(_validator);
            return _validator;
        }

        /// <summary>
        /// 获取所有分组的验证不通过数量
        /// </summary>
        /// <returns></returns>
        public int GetErrorCount()
        {
            return 0;
        }

        /// <summary>
        /// 获取某分组验证不能过数目
        /// </summary>
        /// <param name="_groupName"></param>
        /// <returns></returns>
        public int GetErrorCount(string _groupName)
        {
            return 0;
        }

        #region 实现观察者接口
        public void GetValidatorStat(ISubject subject)
        {
            //根据subject中的信息，记录到汇总信息中
            //subject.GroupName;
            //subject.Ignore;
            //subject.IsPass;
            //subject.ErrorMessage;
        }
        #endregion


        /// <summary>
        /// 生成客户端验证json代码
        /// </summary>
        /// <returns></returns>
        public void RenderClinetValidator()
        {
            RenderClinetValidator(null);
        }

        /// <summary>
        /// 是否存在页面注册区域
        /// </summary>
        /// <returns>存在的区域枚举</returns>
        private FormOrHeader GetRegisterRegion()
        {
            cPage = (Page)HttpContext.Current.Handler;
            if (cPage.Header != null)
            {
                return FormOrHeader.Header;
            }
            else if (cPage.Form != null)
            {
                return FormOrHeader.Form;
            }
            return FormOrHeader.Null;
        }

        /// <summary>
        /// 生成客户端验证json代码
        /// </summary>
        /// <param name="_clientValidatorName">客户端验证器名称</param>
        /// <returns></returns>
        public void RenderClinetValidator(string _clientValidatorName)
        {
            FormOrHeader formOrHeader = GetRegisterRegion();
            if (formOrHeader == FormOrHeader.Null)
                throw new Exception("对不起，页面不存在必须存在标记为\"runat=server\"的Form或是Header标记！请确认！");

            //设置客户端验证对象名
            if (!string.IsNullOrEmpty(_clientValidatorName))
                this.clientValidatorName = _clientValidatorName;

            //按组名排序
            validatorList.Sort(new GroupComparer());

            renderString = new StringBuilder();
            renderString.AppendLine("<script type='text/javascript'>");
            renderString.AppendLine("var " + clientValidatorName + ";");
            renderString.AppendLine("function InitValidator(){");
            renderString.AppendLine(clientValidatorName + "=new MyValidator(" + clientValidatorName + "Container);");
            renderString.AppendLine("}");
            renderString.AppendLine("BindEvent(window,'onload',InitValidator);");
            renderString.AppendLine("var " + clientValidatorName + "Container={");
            int i = 0;
            string currentGroupName;
            string preGroupName;
            string nextGroupName;
            int totalCount = validatorList.Count;
            foreach (ISubject o in validatorList)
            {
                //设置组名
                currentGroupName = validatorList[i].GroupName;
                preGroupName = validatorList[(i - 1) < 0 ? 0 : (i - 1)].GroupName;
                nextGroupName = validatorList[(i + 1) > totalCount - 1 ? totalCount - 1 : (i + 1)].GroupName;
                if (i == 0)
                    renderString.Append(currentGroupName + ":{");
                if (currentGroupName != preGroupName)
                {
                    renderString.Append("}");
                    renderString.Append("," + currentGroupName + ":{");
                }

                i++;
                renderString.Append(o.JsonString);
                if (i != validatorList.Count)
                    if (currentGroupName == nextGroupName)
                        renderString.Append(o.JsonString == string.Empty ? "" : ",");
            }
            renderString.Append("}");
            renderString.AppendLine("};");
            renderString.AppendLine("</script>");

            //加载图片
            string imageTemplate = "<img id='falseIcon' src='{0}' style='display:none'>";
            LiteralControl imageUrlLiterl = new LiteralControl(string.Format(imageTemplate, cPage.ClientScript.GetWebResourceUrl(this.GetType(), "Validator.Resources.icons.gif")));
            cPage.Page.Controls.AddAt(2, imageUrlLiterl);
            //装载样式
            string includeTemplate = "<link rel='stylesheet' text='text/css' href='{0}' />";
            string includeLocation = cPage.ClientScript.GetWebResourceUrl(this.GetType(), "Validator.Resources.validator.css");
            LiteralControl includeLocationLiteral = new LiteralControl(String.Format(includeTemplate, includeLocation));
            //装载js
            string jsTemplate = "<script src='{0}' type='text/javascript'></script>";
            string scriptLocation = cPage.ClientScript.GetWebResourceUrl(this.GetType(), "Validator.Resources.MyValidator.js");
            LiteralControl scriptLocationLiteral = new LiteralControl(String.Format(jsTemplate, scriptLocation));


            if (formOrHeader == FormOrHeader.Header)
            {
                cPage.Header.Controls.Add(includeLocationLiteral);
                cPage.Header.Controls.Add(scriptLocationLiteral);
                cPage.Header.Controls.Add(new LiteralControl(renderString.ToString()));
            }
            else
            {
                cPage.Controls.AddAt(1, includeLocationLiteral);
                cPage.Controls.AddAt(1, scriptLocationLiteral);
                cPage.ClientScript.RegisterClientScriptBlock(cPage.GetType(), this.clientValidatorName, renderString.ToString());
            }
        }

        /// <summary>
        /// 验证所有组
        /// </summary>
        /// <returns>组验证调用函数</returns>
        public string Checked()
        {
            return Checked("_All");
        }

        /// <summary>
        /// 验证特定组
        /// </summary>
        /// <param name="groupName">组名("_All"表示验证所有组)</param>
        /// <returns>组验证调用函数</returns>
        public string Checked(string _groupName)
        {
            string checkGroup = "_All";
            if (!string.IsNullOrEmpty(_groupName))
                checkGroup = _groupName;
            return clientValidatorName + ".ValidateByGroup('" + checkGroup + "');";
        }
    }

    /// <summary>
    /// Form或Header
    /// </summary>
    public enum FormOrHeader : byte
    {
        /// <summary>
        /// 头部
        /// </summary>
        Header,
        /// <summary>
        /// 表单
        /// </summary>
        Form,
        /// <summary>
        /// 无
        /// </summary>
        Null
    }
}
